package com.companyName.sample.data.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.io.Serializable;

@Configuration
//@EnableAutoConfiguration
@ConfigurationProperties(prefix = "spring.redis", ignoreUnknownFields = true)
public class RedisConfig {
	private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class);
	// max number of redis instances
	private int maxActive;

	// max number of idle connections
	private int maxIdle;

	// max wait time
	private long maxWait;

	// if test the availability of the new jedis instance (ping())
	private boolean testOnBorrow;

	// if test the availability of the new jedis instance (ping())
	private boolean testOnReturn;

	// redis server ip
	private String host;

	// redis server port
	private int port;

	public int getMaxActive() {
		return maxActive;
	}

	public void setMaxActive(int maxActive) {
		this.maxActive = maxActive;
	}

	public int getMaxIdle() {
		return maxIdle;
	}

	public void setMaxIdle(int maxIdle) {
		this.maxIdle = maxIdle;
	}

	public long getMaxWait() {
		return maxWait;
	}

	public void setMaxWait(long maxWait) {
		this.maxWait = maxWait;
	}

	public boolean isTestOnBorrow() {
		return testOnBorrow;
	}

	public void setTestOnBorrow(boolean testOnBorrow) {
		this.testOnBorrow = testOnBorrow;
	}

	public boolean isTestOnReturn() {
		return testOnReturn;
	}

	public String getHost() {
		return host;
	}

	public void setHost(String host) {
		this.host = host;
	}

	public void setTestOnReturn(boolean testOnReturn) {
		this.testOnReturn = testOnReturn;
	}



	public int getPort() {
		return port;
	}

	public void setPort(int port) {
		this.port = port;
	}

	@Bean
	@ConditionalOnMissingBean
	public RedisConnectionFactory jedisConnectionFactory() {
		logger.info("create jedis pool from: {}:{}", this.getHost(), this.getPort());
		JedisPoolConfig poolConfig = new JedisPoolConfig();
		poolConfig.setMaxTotal(this.getMaxActive());//maxActive
		poolConfig.setMaxIdle(this.getMaxIdle()); // maxIdle=8
		poolConfig.setMaxWaitMillis(this.getMaxWait());//.maxWait=-1
		poolConfig.setTestOnBorrow(this.isTestOnBorrow());//
		poolConfig.setTestOnReturn(this.isTestOnReturn());

		JedisConnectionFactory ob = new JedisConnectionFactory(poolConfig);
		ob.setUsePool(true);
		ob.setHostName(this.getHost());
		ob.setPort(this.getPort());
		return ob;
	}


	@Bean
//	@ConditionalOnMissingBean
	public RedisTemplate redisTemplate(){
		RedisTemplate<StringRedisSerializer, Serializable> rt = new RedisTemplate<>();
		rt.setConnectionFactory(jedisConnectionFactory());
		StringRedisSerializer stringSerializer = new StringRedisSerializer();
		JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
		rt.setKeySerializer(stringSerializer);
		rt.setValueSerializer(jdkSerializationRedisSerializer);
		rt.setHashKeySerializer(stringSerializer);
		rt.setHashValueSerializer(jdkSerializationRedisSerializer);
		rt.afterPropertiesSet();
		rt.setEnableTransactionSupport(true);
		return rt;
	}

	@Bean(name="jedisPool")
	@ConditionalOnMissingBean
	public JedisPool getJedisPool() {
//		logger.info("create jedis pool from: {}:{}", this.getHost(), this.getPort());
		JedisPoolConfig config = new JedisPoolConfig();
		config.setMaxTotal(this.getMaxActive());
		config.setMaxIdle(this.getMaxIdle());
		config.setMaxWaitMillis(this.getMaxWait());
		config.setTestOnBorrow(this.isTestOnBorrow());
		config.setTestOnReturn(this.isTestOnReturn());
		return new JedisPool(config, this.getHost(), this.getPort());
	}

}
